﻿Namespace IMDB
    Public Class Manager
        Public Shared Function GetMovieInfo(ByVal imdbMoviePageUrl As Uri) As Entities.OpenMediaInfo.FeatureInfo
            Dim clsReq As System.Net.WebRequest
            clsReq = System.Net.WebRequest.Create(imdbMoviePageUrl)
            Using clsRes As System.Net.WebResponse = clsReq.GetResponse()
                Using clsStream As System.IO.Stream = clsRes.GetResponseStream()
                    Return GetMovieInfo(clsStream)
                End Using
            End Using

        End Function

        Public Shared Function GetMovieInfo(ByVal stream As IO.Stream) As Entities.OpenMediaInfo.FeatureInfo
            Dim strHtml As String
            Using clsSR As New IO.StreamReader(stream)
                strHtml = clsSR.ReadToEnd
            End Using
            Dim clsD As MIL.Html.HtmlDocument
            clsD = MIL.Html.HtmlDocument.Create(strHtml)
            Return GetMovieInfo(clsD)
        End Function

        Private Shared Function GetMovieInfo(ByVal document As MIL.Html.HtmlDocument) As Entities.OpenMediaInfo.FeatureInfo
            Dim clsRet As New Entities.OpenMediaInfo.FeatureInfo

            clsRet.Ids = GetIds(document)

            clsRet.Directors = GetDirectors(document)
            clsRet.Writers = GetWriters(document)

            clsRet.Genres = GetGenres(document)
            clsRet.Tagline = GetTagline(document)
            clsRet.PlotSummary = GetPlot(document)
            clsRet.ReleaseDate = GetReleaseDate(document)
            clsRet.Description = GetMetaDataByName(document.Nodes, "description")
            clsRet.Title = GetTitle(document)
            clsRet.Year = GetYear(document)

            clsRet.InformationUpdated = Now.ToUniversalTime
            clsRet.InformationUpdatedBy = System.Environment.UserName
            clsRet.Poster = GetPoster(document)
            clsRet.Cast = GetCast(document)
            clsRet.Certifications = GetCertifications(document)

            clsRet.InformationSource = Entities.OpenMediaInfo.InformationSource.Automatically
            Return clsRet
        End Function

        Public Shared Function ExtractTitleFromFilename(ByVal fileName As String) As String
            Dim strFileName As String = IO.Path.GetFileNameWithoutExtension(fileName).Trim
            strFileName = strFileName.Replace("."c, " "c).Trim

            Dim iPos As Integer = strFileName.IndexOf("["c)
            While iPos > 0
                Dim iPos2 As Integer = strFileName.IndexOf("]"c, iPos + 1)
                strFileName = strFileName.Substring(0, iPos).Trim & strFileName.Substring(iPos2 + 1)
                iPos = strFileName.IndexOf("["c)
            End While

            iPos = strFileName.IndexOf("("c)
            While iPos > 0
                Dim iPos2 As Integer = strFileName.IndexOf(")"c, iPos + 1)
                strFileName = strFileName.Substring(0, iPos).Trim & strFileName.Substring(iPos2 + 1)
                iPos = strFileName.IndexOf("("c)
            End While

            If strFileName.ToLower.EndsWith(", the") Then
                strFileName = "The " & strFileName.Substring(0, strFileName.Length - 5)
            ElseIf strFileName.ToLower.EndsWith(", die") Then
                strFileName = "Die " & strFileName.Substring(0, strFileName.Length - 5)
            ElseIf strFileName.ToLower.EndsWith(", das") Then
                strFileName = "Das " & strFileName.Substring(0, strFileName.Length - 5)
            ElseIf strFileName.ToLower.EndsWith(", der") Then
                strFileName = "Der " & strFileName.Substring(0, strFileName.Length - 5)
            End If
            Return strFileName
        End Function



#Region "  Parsing of IMDB Html Pages "

        Private Shared Function GetCertifications(ByVal doc As MIL.Html.HtmlDocument) As Generic.List(Of Entities.OpenMediaInfo.Certification)
            Dim clsElement As MIL.Html.HtmlElement = MILHelper.FindElementByText(doc.Nodes, "certification:")

            Dim aRet As New Generic.List(Of Entities.OpenMediaInfo.Certification)

            If clsElement IsNot Nothing Then
                Dim clsNode As MIL.Html.HtmlNode = clsElement.Next
                While clsNode IsNot Nothing
                    clsElement = TryCast(clsNode, MIL.Html.HtmlElement)
                    If clsElement IsNot Nothing Then
                        If clsElement.Name.ToLower.Trim = "a" Then
                            Dim iPos As Integer = clsElement.Text.IndexOf(":"c)
                            If iPos >= 0 Then
                                Dim clsCert As New Entities.OpenMediaInfo.Certification
                                Dim strCountry As String = clsElement.Text.Substring(0, iPos)
                                Dim strLevel As String = clsElement.Text.Substring(iPos + 1).Trim
                                clsCert.Country = strCountry
                                clsCert.Level = strLevel

                                If TypeOf clsElement.Next Is MIL.Html.HtmlElement Then
                                    Dim clsT As MIL.Html.HtmlElement = CType(clsElement.Next, MIL.Html.HtmlElement)
                                    If clsT.Name.ToLower = "i" Then
                                        Dim strText As String = clsT.HTML
                                        Dim iPos2 As Integer = strText.IndexOf("("c)
                                        If iPos2 > 0 Then
                                            Dim iPos3 As Integer = strText.LastIndexOf(")"c)
                                            If iPos3 > iPos2 Then
                                                clsCert.Note = strText.Substring(iPos2 + 1, iPos3 - iPos2 - 1)
                                            End If
                                        End If
                                    End If
                                End If

                                aRet.Add(clsCert)
                            End If
                        End If
                    End If
                    clsNode = clsNode.Next
                End While
            End If
            Return aRet
        End Function

        Private Shared Function GetCast(ByVal doc As MIL.Html.HtmlDocument) As Generic.List(Of Entities.OpenMediaInfo.Contributer)
            Dim clsElement As MIL.Html.HtmlElement
            clsElement = MILHelper.FindElement(doc.Nodes, "table", "class", "cast")
            If clsElement Is Nothing Then Return Nothing

            Dim clsNode As MIL.Html.HtmlNode = clsElement.FirstChild

            Dim aRet As New Generic.List(Of Entities.OpenMediaInfo.Contributer)
            While clsNode IsNot Nothing
                clsElement = TryCast(clsNode, MIL.Html.HtmlElement)
                If clsElement IsNot Nothing AndAlso clsElement.Name.ToLower = "tr" Then
                    Dim clsContributer As Entities.OpenMediaInfo.Contributer = GetCastPersonFromTableRow(clsElement.Nodes)
                    If clsContributer IsNot Nothing Then aRet.Add(clsContributer)
                End If

                clsNode = clsNode.Next
            End While

            Return aRet
        End Function

        Private Shared Function GetCastPersonFromTableRow(ByVal nodes As MIL.Html.HtmlNodeCollection) As Entities.OpenMediaInfo.Contributer
            Dim clsTdName As MIL.Html.HtmlElement = MILHelper.FindElement(nodes, "td", "class", "nm")
            If clsTdName Is Nothing Then Return Nothing

            Dim strName As String
            Dim strId As String
            Dim strPart As String

            If TypeOf clsTdName.FirstChild Is MIL.Html.HtmlElement Then
                Dim clsElName As MIL.Html.HtmlElement = CType(clsTdName.FirstChild, MIL.Html.HtmlElement)
                If clsElName.Name.ToLower = "a" Then
                    strName = clsElName.Text
                    strId = GetNameId(clsElName.Attributes)
                Else
                    Return Nothing
                End If
            Else
                Return Nothing
            End If

            Dim clsTdCharacter As MIL.Html.HtmlElement = MILHelper.FindElement(nodes, "td", "class", "char")
            If clsTdCharacter Is Nothing Then Return Nothing

            If TypeOf clsTdCharacter.FirstChild Is MIL.Html.HtmlElement Then
                Dim clsElCharacter As MIL.Html.HtmlElement = CType(clsTdCharacter.FirstChild, MIL.Html.HtmlElement)
                If clsElCharacter.Name.ToLower = "a" Then
                    strPart = clsElCharacter.Text
                Else
                    Return Nothing
                End If
            ElseIf TypeOf clsTdCharacter.FirstChild Is MIL.Html.HtmlText Then
                Dim clsTxCharacter As MIL.Html.HtmlText = CType(clsTdCharacter.FirstChild, MIL.Html.HtmlText)
                strPart = clsTxCharacter.Text
            Else
                Return Nothing
            End If

            Dim clsRet As New Entities.OpenMediaInfo.Contributer
            clsRet.Name = strName
            clsRet.Ids.Add(strId)
            clsRet.Part = strPart
            Return clsRet
        End Function

        Private Shared Function GetAttribute(ByVal element As MIL.Html.HtmlElement, ByVal attrName As String) As MIL.Html.HtmlAttribute
            For Each clsAttr As MIL.Html.HtmlAttribute In element.Attributes
                If clsAttr.Name.ToLower = attrName Then Return clsAttr
            Next
            Return Nothing
        End Function

        Private Shared Function GetDirectors(ByVal doc As MIL.Html.HtmlDocument) As Generic.List(Of Entities.OpenMediaInfo.Contributer)
            Dim clsElement As MIL.Html.HtmlElement = MILHelper.FindElementByText(doc.Nodes, "directors:")
            If clsElement Is Nothing Then clsElement = MILHelper.FindElementByText(doc.Nodes, "director:")
            Return GetContributersFromElement(clsElement)
        End Function

        Private Shared Function GetWriters(ByVal doc As MIL.Html.HtmlDocument) As Generic.List(Of Entities.OpenMediaInfo.Contributer)
            Dim clsElement As MIL.Html.HtmlElement = MILHelper.FindElementByText(doc.Nodes, "writers:")
            If clsElement Is Nothing Then clsElement = MILHelper.FindElementByText(doc.Nodes, "writer:")
            Return GetContributersFromElement(clsElement)
        End Function

        Private Shared Function GetGenres(ByVal doc As MIL.Html.HtmlDocument) As Generic.List(Of Entities.OpenMediaInfo.Genre)
            Dim clsElement As MIL.Html.HtmlElement = MILHelper.FindElementByText(doc.Nodes, "genre:")

            Dim aRet As New Generic.List(Of Entities.OpenMediaInfo.Genre)

            If clsElement IsNot Nothing Then
                Dim clsNode As MIL.Html.HtmlNode = clsElement.Next
                While clsNode IsNot Nothing
                    clsElement = TryCast(clsNode, MIL.Html.HtmlElement)
                    If clsElement IsNot Nothing Then
                        If clsElement.Text.ToLower.Trim = "more" Then
                            Exit While
                        ElseIf clsElement.Name.ToLower.Trim = "a" Then
                            Dim clsGenre As New Entities.OpenMediaInfo.Genre
                            clsGenre.Name = clsElement.Text
                            aRet.Add(clsGenre)
                        End If
                    End If
                    clsNode = clsNode.Next
                End While
            End If
            Return aRet
        End Function

        Private Shared Function GetTagline(ByVal doc As MIL.Html.HtmlDocument) As String
            Return GetSimpleTextInfo(doc, "tagline:")
        End Function
        Private Shared Function GetPlot(ByVal doc As MIL.Html.HtmlDocument) As String
            Return GetSimpleTextInfo(doc, "plot:")
        End Function
        Private Shared Function GetReleaseDate(ByVal doc As MIL.Html.HtmlDocument) As String
            Return GetSimpleTextInfo(doc, "release date:")
        End Function

        Private Shared Function GetTitle(ByVal doc As MIL.Html.HtmlDocument) As String
            Dim strText As String = GetMetaDataByName(doc.Nodes, "title")
            If strText Is Nothing Then Return Nothing
            Dim iPos As Integer = strText.IndexOf("("c)
            If iPos < 0 Then Return Nothing
            Return strText.Substring(0, iPos - 1).Trim
        End Function
        Private Shared Function GetYear(ByVal doc As MIL.Html.HtmlDocument) As String
            Dim strText As String = GetMetaDataByName(doc.Nodes, "title")
            If strText Is Nothing Then Return Nothing
            Dim iPos As Integer = strText.IndexOf("("c)
            If iPos < 0 Then Return Nothing
            Dim iPos2 As Integer = strText.IndexOf(")"c, iPos + 1)
            If iPos2 < 0 Then Return Nothing
            Return strText.Substring(iPos + 1, iPos2 - iPos - 1).Trim
        End Function

        Private Shared Function GetMetaDataByName(ByVal nodes As MIL.Html.HtmlNodeCollection, ByVal name As String) As String
            For Each clsNode As MIL.Html.HtmlNode In nodes
                If TypeOf clsNode Is MIL.Html.HtmlElement Then
                    Dim clsElement As MIL.Html.HtmlElement = CType(clsNode, MIL.Html.HtmlElement)
                    If clsElement.Name.ToLower = "meta" Then
                        Dim blnOk As Boolean = False
                        For Each clsAttr As MIL.Html.HtmlAttribute In clsElement.Attributes
                            If clsAttr.Name.ToLower.Trim = "name" Then
                                If clsAttr.Value.ToLower.Trim.Replace("""", String.Empty) = name Then
                                    blnOk = True
                                    Exit For
                                End If
                            End If
                        Next
                        If blnOk Then
                            For Each clsAttr As MIL.Html.HtmlAttribute In clsElement.Attributes
                                If clsAttr.Name.ToLower.Trim = "content" Then
                                    Return clsAttr.Value
                                End If
                            Next
                            Return Nothing
                        End If
                    End If
                    Dim strRes As String = GetMetaDataByName(clsElement.Nodes, name)
                    If strRes IsNot Nothing Then Return strRes
                End If
            Next
            Return Nothing
        End Function

        Private Shared Function GetSimpleTextInfo(ByVal doc As MIL.Html.HtmlDocument, ByVal label As String) As String
            Dim clsElement As MIL.Html.HtmlElement = MILHelper.FindElementByText(doc.Nodes, label)
            If clsElement IsNot Nothing Then
                Dim clsNode As MIL.Html.HtmlNode = clsElement.Next
                If TypeOf clsNode Is MIL.Html.HtmlText Then
                    Return CType(clsNode, MIL.Html.HtmlText).Text
                End If
            End If
            Return Nothing
        End Function

        Private Shared Function GetContributersFromElement(ByVal element As MIL.Html.HtmlElement) As Generic.List(Of Entities.OpenMediaInfo.Contributer)

            Dim aList As New Generic.List(Of Entities.OpenMediaInfo.Contributer)
            Dim clsLastNodesPerson As Entities.OpenMediaInfo.Contributer = Nothing
            If element IsNot Nothing Then
                Dim clsNode As MIL.Html.HtmlNode = element.Next
                While clsNode IsNot Nothing
                    element = TryCast(clsNode, MIL.Html.HtmlElement)
                    If element IsNot Nothing AndAlso element.Name.ToLower.Trim = "a" Then
                        Dim clsPerson As New Entities.OpenMediaInfo.Contributer
                        clsPerson.Name = element.Text
                        Dim strId As String = GetNameId(element.Attributes)
                        If Not String.IsNullOrEmpty(strId) Then
                            clsPerson.Ids.Add(strId)
                            aList.Add(clsPerson)
                            clsLastNodesPerson = clsPerson
                        Else
                            clsLastNodesPerson = Nothing
                        End If
                        'clsPerson.Ids.Add("pomdb:121")
                    ElseIf TypeOf clsNode Is MIL.Html.HtmlText And clsLastNodesPerson IsNot Nothing Then
                        Dim clsT As MIL.Html.HtmlText = CType(clsNode, MIL.Html.HtmlText)
                        clsLastNodesPerson.Part = GetTypeFromText(clsT.Text)
                    Else
                        clsLastNodesPerson = Nothing
                    End If
                    clsNode = clsNode.Next
                End While
            End If
            Return aList
        End Function

        Private Shared Function GetTypeFromText(ByVal text As String) As String
            If text Is Nothing Then Return Nothing
            Dim iPos As Integer = text.IndexOf("("c)
            If iPos < 0 Then Return Nothing
            Dim iPos2 As Integer = text.IndexOf(")"c, iPos + 1)
            If iPos2 < 0 Then Return Nothing
            Return text.Substring(iPos + 1, iPos2 - iPos - 1)
        End Function

        Private Shared Function GetNameId(ByVal attrs As MIL.Html.HtmlAttributeCollection) As String
            For Each clsAttr As MIL.Html.HtmlAttribute In attrs
                If clsAttr.Name.ToLower.Trim = "href" Then
                    Dim iPos As Integer = clsAttr.Value.ToLower.IndexOf("/nm")
                    If iPos < 0 Then Return Nothing
                    Dim iPos2 As Integer = clsAttr.Value.IndexOf("/"c, iPos + 1)
                    If iPos2 < 0 Then Return Nothing
                    Dim strId As String = clsAttr.Value.Substring(iPos + 1, iPos2 - iPos - 1)
                    Return String.Format("imdb:{0}", strId)
                End If
            Next
            Return String.Empty
        End Function


        Private Shared Function GetIds(ByVal doc As MIL.Html.HtmlDocument) As Generic.List(Of String)
            Dim clsElement As MIL.Html.HtmlElement = MILHelper.FindElement(doc.Nodes, "a", "name", "poster")
            If clsElement Is Nothing Then Return Nothing

            Dim clsAttr As MIL.Html.HtmlAttribute = GetAttribute(clsElement, "href")
            If clsAttr Is Nothing Then Return Nothing

            Dim aRet As New Generic.List(Of String)
            Dim strId As String = OpenMediaInfo.IMDB.Manager.GetImdbIdFromUri(clsAttr.Value)
            aRet.Add(String.Format("imdb:{0}", strId))
            Return aRet
        End Function

        Private Shared Function GetPoster(ByVal doc As MIL.Html.HtmlDocument) As Entities.OpenMediaInfo.BinaryFile
            Dim clsElement As MIL.Html.HtmlElement = MILHelper.FindElement(doc.Nodes, "a", "name", "poster")

            Dim strUrl As String = Nothing

            If clsElement IsNot Nothing Then
                Dim clsNode As MIL.Html.HtmlNode = clsElement.FirstChild
                While clsNode IsNot Nothing
                    If TypeOf clsNode Is MIL.Html.HtmlElement Then
                        clsElement = CType(clsNode, MIL.Html.HtmlElement)
                        If clsElement.Name.ToLower = "img" Then
                            For Each clsAttr As MIL.Html.HtmlAttribute In clsElement.Attributes
                                If clsAttr.Name.ToLower = "src" Then
                                    strUrl = clsAttr.Value
                                    Exit While
                                End If
                            Next
                        End If
                    End If
                    clsNode = clsNode.Next
                End While
            End If
            If strUrl IsNot Nothing Then
                Dim bBuf As New Generic.List(Of Byte)
                Dim clsReq As System.Net.WebRequest
                clsReq = System.Net.WebRequest.Create(strUrl)
                Using clsRes As System.Net.WebResponse = clsReq.GetResponse()
                    Using clsStream As System.IO.Stream = clsRes.GetResponseStream()
                        Dim iByte As Integer = clsStream.ReadByte
                        While iByte <> -1
                            bBuf.Add(CByte(iByte))
                            iByte = clsStream.ReadByte
                        End While
                    End Using
                End Using
                Dim iPos As Integer = strUrl.LastIndexOf("."c)
                If iPos < 0 Then Return Nothing
                If iPos + 1 >= strUrl.Length Then Return Nothing
                Dim strExt As String = strUrl.Substring(iPos + 1).ToLower
                Dim clsRet As New Entities.OpenMediaInfo.BinaryFile
                Select Case strExt
                    Case "jpg", "jpeg"
                        clsRet.Type = "image/jpg"
                    Case "gif"
                        clsRet.Type = "image/gif"
                    Case "png"
                        clsRet.Type = "image/png"
                    Case Else
                        Return Nothing
                End Select
                clsRet.Data = bBuf.ToArray
                Return clsRet
            Else
                Return Nothing
            End If
        End Function



#End Region
        Public Shared Function IsImdbTitlePage(ByVal uri As System.Uri) As Boolean
            If uri Is Nothing Then
                Return False
            Else
                Return IsImdbTitlePage(uri.ToString)
            End If
        End Function
        Public Shared Function IsImdbTitlePage(ByVal url As String) As Boolean
            If url Is Nothing Then
                Return False
            Else
                Return url.ToLower.IndexOf("imdb.com/title/tt") >= 0
            End If
        End Function
        Public Shared Function GetImdbIdFromUri(ByVal urlOrUrlFragment As String) As String
            Dim iPos As Integer = urlOrUrlFragment.ToLower.IndexOf("/tt")
            If iPos < 0 Then Return Nothing
            Dim iPos2 As Integer = urlOrUrlFragment.IndexOf("/"c, iPos + 1)
            If iPos2 < 0 Then iPos2 = urlOrUrlFragment.Length

            Dim aRet As New Generic.List(Of String)
            Dim strId As String = urlOrUrlFragment.Substring(iPos + 1, iPos2 - iPos - 1)
            Return strId
        End Function
        Public Shared Function GetImdbIdFromUri(ByVal uri As System.Uri) As String
            Dim strText As String = uri.AbsolutePath
            Return GetImdbIdFromUri(strText)
        End Function
        Public Shared Function GetUriFromId(ByVal id As String) As Uri
            Return New Uri(String.Format("http://www.imdb.com/title/{0}/", id))
        End Function

       
    End Class

End Namespace